import { EncodeUtils } from "./EncodeUtils";
import Rwebsocket from 'reconnecting-websocket'
import { RingBuffer } from "./RingBuffer";
import { MessageMap } from "./MessageMap";
import { MessageEvent2 } from "./MessageEvent2";
import { NetMsgType } from "@/netBase/NetMsgType";
import { i18n } from '@/languages/index';
import { showToast } from '@nutui/nutui';
import pinia from '@/store/index';
import { User } from '@/store/user';
import { Local } from "@/utils/storage";
import { getFastestUrl } from "@/utils/useStoreMethods";
import { checkVersion } from "@/utils/useNetMethods";

var timeId: string | number | NodeJS.Timeout | undefined, reconnect: any, times = 4
// import { NetPacket } from "@/netBase/NetPacket";
// import { NetEnumDef } from "@/netBase/NetEnumDef";
// 改成单例模式
class H5Websocket {
    // 定义一个对象 用于接收websocket对象
    public instance: Rwebsocket | null = null;
    private ringBuffer = new RingBuffer();
    // wenbsocket数据处理注册事件
    public handler?: (params: any) => void;
    packageCount: number = 1;
    constructor() {
        // MessageEvent2.addMsgEvent(NetPacket.notify_login_result().getMsgID(), this.retryConnectRecv.bind(this));
    }

    // 创建连接
    conectWebsocket = () => {
        // 对webSocket连接创建回调
        times--
        if (times > 0) {
            return new Promise(async (resolve, reject) => {
                const ipPort = await getFastestUrl()
                this.instance = new Rwebsocket(ipPort);
                this.instance.onopen = async (evt) => {
                    timeId && window.clearInterval(timeId)
                    if (reconnect) {
                        console.log('ios重连成功');
                        times = 4
                        reconnect = false
                    }
                    console.log("websocket-连接成功", evt);
                    setTimeout(() => {
                        checkVersion();
                    }, 200);
                    resolve(evt);
                };
                // 服务器返回断开
                this.instance.onclose = async (_event: any) => {
                    // console.log('===============>2', event);
                    // showToast.fail(i18n.global.t('sever_err_disconnect'))
                    console.log("websocket-断开连接");
                    this.close()
                    this.instance?.close()
                    this.instance = null
                    clearInterval(timeId)
                    let isiOS = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
                    if (isiOS) {
                        reconnect = true;
                        if (times == 3) {
                            timeId = window.setInterval(this.conectWebsocket, 0);
                        } else {
                            timeId = window.setInterval(this.conectWebsocket, 3000);
                        }

                    }

                };
                this.instance.onmessage = (event) => {
                    // console.log('===============>1', event);
                    this.onMessageHandler(event)
                };
                // 服务器返回链接错误
                this.instance.onerror = (evt) => {
                    // console.log(evt);
                    this.close()
                    this.instance?.close()
                    this.instance = null
                    showToast.fail(i18n.global.t('sever_err_connection_rror'))
                    console.log("websocket-连接错误");
                    reject(evt)
                };
            })
        }

    }
    // //注册监听事件
    // resgisterHandler = (cb: (evt: MessageEvent<any>) => void)=> {
    //     this.handler = cb;
    // }
    // // 清除注册事件
    // clearHandler =()=> {
    //     this.handler = () => { };
    // }
    // 发送消息
    sendMessageHandler = (data: any) => {
        let msg = JSON.parse(JSON.stringify(data))
        delete msg.build
        delete msg.decode
        delete msg.encode
        delete msg.getMsgID
        console.log(`发送的协议为: ==> ${this.getMsgType(data.getMsgID())}
发送的数据为：==>`, msg);

        //消息包编号，服务器需要用到
        let buf: any = [];
        let count = this.calcPacketCount();
        EncodeUtils.uInt8ToByte(count, buf);

        //编码消息体
        data.build(buf);

        //编码整个包头，不包括自身的4个字节
        let bodylen = EncodeUtils.swab32_msg_total_length(buf.length);
        let bodyLenBuf: any[] = [];
        EncodeUtils.encode_msg_total_length(bodylen, bodyLenBuf);

        //把bodylen放到buf最前面
        for (let i = 3; i >= 0; --i) {
            buf.unshift(bodyLenBuf[i]);
        }
        let sendbuffer = new Uint8Array(buf).buffer;
        this.instance?.send(sendbuffer);
    }
    // 消息事件监听
    onMessageHandler = async (event: MessageEvent<any>) => {
        if (typeof event.data == "string") {
            let array = [];
            for (let i = 0; i < event.data.length; i++) {
                array.push(event.data.charCodeAt(i));
            }
            // console.log("array:",array);
            let buf = new Uint8Array(array);
            this.ReceiveMessage(buf);
            return;
        }

        let reader = new FileReader();
        reader.readAsArrayBuffer(event.data);
        let self = this;
        reader.onload = function () {
            let buf = new Uint8Array(reader.result as any);
            //先存入队列中
            self.ReceiveMessage(buf);
        };

        // const arrayBuffer = await event.data.arrayBuffer();
        // this.handler?.call(this, arrayBuffer);
    }
    // 断开连接
    close = async () => {
        if (Local.get('user') && Local.get('user').token) {
            await User(pinia).setLoadingEnd(false)
        }
        this.packageCount = 1;
        this.instance?.close();
    }
    ReceiveMessage = (buf: any) => {
        var len = buf.byteLength;
        if (buf == undefined || buf == null || len == 0) {
            return;
        }
        for (var i = 0; i < len; ++i) {
            this.ringBuffer.Push(buf[i]);
        }
        while (true) {
            var receivedlength = this.ringBuffer.DataLength();
            if (receivedlength < 4) {
                return;
            }

            let bodyLen = this.ringBuffer.decode_msg_total_length();

            if (bodyLen < 1) {
                return;
            }

            if (receivedlength < bodyLen + 4) {
                return;
            }
            this.DecodeMessage(bodyLen);
        }
    }
    // 解码消息体
    DecodeMessage = (bodyLen: number) => {
        this.ringBuffer.addHead(4); //先去掉4个字节的包长度，再开始解析msg_id
        let msgID = this.ringBuffer.decode_msg_id();

        let messageStruct = MessageMap.getMessage(msgID);

        if (messageStruct == null) {
            //找不到对应的解码结构体时，循环消息ringbuffer的标识也要往后移，跳过这条消息的数据
            this.ringBuffer.addHead(bodyLen - 4);
            console.log("msgID not register", msgID);
            return;
        }
        let message = this.ringBuffer.decode_msg_body(messageStruct, bodyLen - 4);
        if (message.code != 1) {
            if (message.message) {
                if (!['account_type_error', 'withdraw_password_can_be_bound', 'get_withdraw_password_status_success', 'withdraw_password_open_success', 'withdraw_password_operate_failed'].includes(message.message)) {
                    console.log('----------***')
                    showToast.fail(i18n.global.t(message.message))
                }

            }
        }
        // console.log("DecodeMessage==>", this.getMsgType(msgID));

        if (![18, 10, 1004].includes(msgID)) {
            console.log(
                `返回协议的id为 ==> ${msgID}
协议字段为 ==> ${this.getMsgType(msgID)}
返回的数据为 ==>`, JSON.parse(JSON.stringify(message))
            );
        }
        //  第二个 net 对应第二个ip地址
        if (msgID == 5) { // 这个事件id监听不到
            MessageEvent2.sendEvent(10086, message);
        }
        MessageEvent2.sendEvent(msgID, message);
    }
    // 获取消息类型
    getMsgType = (msgID: number) => {
        let msgType: any = NetMsgType.msgType
        for (const key in msgType) {
            if (msgType[key] == msgID) {
                return key;
            }
        }
    }
    calcPacketCount = () => {
        let count = this.packageCount++;
        if (this.packageCount > 255) {
            this.packageCount = 1;
        }

        return count;
    }

}
export default new H5Websocket();

